package agenda;

import java.io.Serializable;
import java.util.*;

/**
 * Classe representativa de uma Agenda
 * 
 * @author emerson borges - emerson.borges@ccc.ufcg.edu.br
 * @author rafael lima    - rafael.ufcg10@gmail.com
 *
 */
public class Agenda implements Serializable {

	private static final long serialVersionUID = 7092502849623840289L;
	private Usuario usuario;
	private List<Contato> contatos;
	private List<Evento> eventosPassados;
	private List<Evento> eventosFuturos;
		
	 public Agenda(){
         eventosFuturos = new ArrayList<Evento>();
         eventosPassados = new ArrayList<Evento>();
         contatos = new ArrayList<Contato>();
     }

	/**
	 * Cria um perfil, inicialmente vazio
	 */
	public void criarPerfilVazio() {
		usuario = new Usuario();		
	}
	
	/**
	 * Metodo para acessar o usuario da agenda 
	 * 
	 * @return usuario
	 */
	public Usuario getUsuario() {
		return usuario;
	}

	/***
	 * atualiza o campo nome do perfil do usuario
	 * 
	 * @param nome
	 * @return void
	 * @throws Exception 
	 */
	public void atualizarNomeDoUsuario(String nome) throws Exception {
		if(nome.equals(null)){
			throw new Exception("Nome nao pode ser nulo.");
		}
		if(nome.equals("")){
			throw new Exception("Nome nao pode ser vazio.");
		}
		usuario.setNome(nome);
	}
	
	/***
	 * Stualiza o campo descricao do perfil do usuario
	 * 
	 * @param descricao
	 * @return void
	 * @throws Exception 
	 */
	public void atualizarDescricaoDoUsuario(String descricao) throws Exception {
		if(descricao.equals(null)){
			throw new Exception("Descricao nao pode ser nulo.");
		}
		if(descricao.equals("")){
			throw new Exception("Descricao nao pode ser vazio.");
		}
		usuario.setDescricao(descricao);
	}

	/***
	 * Atualiza o campo email do perfil do usuario
	 * 
	 * @param email
	 * @return void
	 * @throws Exception 
	 */
	public void atualizarEmailDoUsuario(String email) throws Exception {
		if(email.equals(null)){
			throw new Exception("Email nao pode ser nulo.");
		}
		if(email.equals("")){
			throw new Exception("Email nao pode ser vazio.");
		}
		usuario.setEmail(email);
	}

	/***
	 * Atualiza os 3 campos do perfil do usuario (nome, descricao e email)
	 * 
	 * @param nome
	 * @param descricao
	 * @param email
	 * @return void
	 * @throws Exception 
	 */
	public void atualizarPerfilDoUsuario(String nome, String descricao, String email) throws Exception {
		if(nome.equals(null) || descricao.equals(null) || email.equals(null)){
			throw new Exception("Nome, descricao ou email nao podem ser nulos.");
		}
		if(nome.equals("") || descricao.equals("") || email.equals("")){
			throw new Exception("Nome, descricao ou email nao podem ser vazios.");
		}
		usuario.setNome(nome);
		usuario.setDescricao(descricao);
		usuario.setEmail(email);
		
	}

	/***
	 * Apaga o perfil do usuario
	 * 
	 * @return void
	 */
	public void apagarPerfilDoUsuario() {
		usuario.setDescricao("");
		usuario.setEmail("");
		usuario.setNome("");
	}

	/***
	 * Retorna o perfil do usuario
	 * 
	 * @return String
	 */
	public String getPerfilDoUsuario() {
		return usuario.toString();
	}

	// comportamentais
	/***
	 * Esse metodo adiciona um novo evento a agenda. Se ja houver um evento no
	 * dia e horario deste novo evento o metodo lan�a uma excecao. Adiciona o
	 * evento em eventos passado ou futuros, comparando o dia e a hora do evento
	 * com o dia e a hora do sitema
	 * 
	 * @param nomeDoEvento
	 *            String
	 * @param data
	 *            String
	 * @param horario
	 *            String
	 * @param duracao
	 *            String
	 * @param descricao
	 *            String
	 * @param tipoDoEvento
	 *            String
	 * @throws Exception
	 *             Lanca excecao caso encontre eventos conflitantes
	 * @return void
	 */
	public void adicionarEventos(String nomeEvento, String dataEvento, String horarioEvento, String duracaoEvento, 
			String descricaoEvento, String tipoEvento) throws Exception {
		Evento novoEvento = new Evento(nomeEvento, dataEvento, horarioEvento, duracaoEvento, descricaoEvento, 
				tipoEvento);

		List<Evento> todosOsEventos = new ArrayList<Evento>();
		todosOsEventos.addAll(eventosFuturos);
		todosOsEventos.addAll(eventosPassados);

		for (Evento evento : todosOsEventos) {
			if (novoEvento.avaliaChoqueEventos(evento)) {
				throw new Exception("Choque de horario");
			}
		}

		GregorianCalendar dataAtual = new GregorianCalendar();
		if (novoEvento.getDataHoraEvento().after(dataAtual.getTime())) {
			eventosFuturos.add(novoEvento);
		} else if (novoEvento.getDataHoraEvento().before(dataAtual.getTime())) {
			eventosPassados.add(novoEvento);
		}
	}

	

	/***
	 * Pega os eventos passados cadastrados na agenda
	 * 
	 * @return List<Evento> ArrayList de eventos passado
	 */
	public List<Evento> getEventosPassados() {
		return eventosPassados;
	}

	/***
	 * Pega os eventos futuros cadastrados na agenda
	 * 
	 * @return ArrayList<Evento>
	 */
	public List<Evento> getEventosFuturos() {
		return eventosFuturos;
	}

	// modificacoes relativas a contato
	// O metodo organiza a ordem alfabetica da lista de contas ao adicionar um
	// contato a ela.

	/***
	 * Retorna todos os contatos cadastrados na agenda
	 * 
	 * @return List<Contato> ArrayList de contatos
	 */
	public List<Contato> getContatos() {
		return contatos;
	}

	/***
	 * Adiciona um contato a agenda
	 * 
	 * @param contato
	 * @return void
	 */
	public void adicionarContato(Contato contato) {
		contatos.add(contato);
		Collections.sort(contatos);
	}

	/***
	 * Romove um contato da lista de contatos existente em agenda
	 * 
	 * @param contato
	 *            Contato return void
	 */
	public void removerContato(Contato contato) {
		contatos.remove(contato);
	}

	/***
	 * Adiciona um contato a um evento
	 * 
	 * @param evento
	 *            Evento
	 * @param contato
	 *            Contato
	 * @return void
	 */
	public void adicionarContatoAEvento(Evento evento, Contato contato) {
		evento.adicionaContato(contato);
	}

	/***
	 * Remove um contato de um evento
	 * 
	 * @param evento
	 *            Evento
	 * @param contato
	 *            Contato
	 * @return void
	 */
	public void removerContatoDeEvento(Evento evento, Contato contato) {
		evento.getListaDeContatos().remove(contato);
	}

	/***
	 * Identifica quais contatos contem uma determinada palavra
	 * 
	 * @param parteDoNome
	 * @return List<Contato>
	 */
	public List<Contato> procuraContato(String parteDoNome) {
		List<Contato> contatosPesquisados = new ArrayList<Contato>();
		for (Contato contato : contatos) {
			if (contato.getNome().toLowerCase().contains(parteDoNome.toLowerCase())) {
				contatosPesquisados.add(contato);
			}
		}

		return contatosPesquisados;
	}

	
	@Override
	public String toString() {
		return usuario.toString();
	}

}